Spring Authorization Server + Oauth2 配置认证服务器与资源服务器

您所在的位置:网站首页 spring security登录原理 Spring Authorization Server + Oauth2 配置认证服务器与资源服务器

Spring Authorization Server + Oauth2 配置认证服务器与资源服务器

2023-05-24 02:24| 来源: 网络整理| 查看: 265

认证、授权服务器 一、文章前述 当一个团队下的项目过多的时候,可能存在每个项目都有各自的认证方式,各自的用户信息库。当团队需要对用户的某些类型的信息做敏感处理、用户信息有针对性的提供等,就需要每一个项目都去修改各自的用户库、代码逻辑,并且改动过程中各自为政,可能出现同一团队信息对外展现形式不统一,导致一些用户认知系统差异并且各自为政会导致重复劳动。在这时候,认证授权服务器就应运而生,同一管理用户信息,规范管理用户信息对外授权,起到一个统一、安全的作用。 目前线上有很多主流的认证、授权方式,比如Oauth2.0,、OIDC(基于Oauth2.0)等。接下来介绍的就是目前的主流实现Oauth2.0认证授权的框架,SpringSecurity。 二、认证服务器 Spring Authorization Server 是 Spring Security 新推出的认证服务器框架。该框架也集成了OIDC,提供了客户端的注册和查询功能。下面开始介绍认证服务器的原理与配置。 整体认证流程

认证获取用户资源时序图 (1).png

1、Spring Security Spring Authorization Server 框架是基于Spring Security 开发,所以在学习 Spring Authorization Server 配置之前,了解一下 Spring Security 框架是有必要的。 Spring Security 架构流程 Spring Security 是基于 Filter 的职责链模式,下面图片是整体的结构:

Pasted image 20230510210600.png 该结构为多SecurityFilterChain模式,/api/** 会一直第一个链条,其余的会按照顺序一个一个向下判断 SecurityFilterChain ,直到找到一个符合的链条。 DelefatingFilterProxy:处于 Spring-Web 中的一个委托用来执行 Spring Security 链条的前置 Filter。具体执行的是:FilterChainProxy SecurityFilterChain:真正执行配置 Spring Security 安全流程的责任链,该责任链的可以动态配置以实现开闭原则。

Spring Security 认证配置 /** * @author 长安 */ @Slf4j @Configuration(proxyBeanMethods = false) public class DefaultSecurityConfig { JwtDecoder jwtDecoder; @Autowired public void setJwtDecoder(JwtDecoder jwtDecoder) { this.jwtDecoder = jwtDecoder; } // @formatter:off @Bean @Order(200) SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { http .cors().and() // 配置路径权限 .authorizeHttpRequests(authorize -> authorize .requestMatchers("/auth/**").hasRole("USER") .requestMatchers("/unAuth/**", "/login", "/favicon.ico").permitAll() .requestMatchers( // 另一种配置的方式 new AntPathRequestMatcher("/h2/**", HttpMethod.GET.name()), new AntPathRequestMatcher("/h2/**", HttpMethod.POST.name()) ).permitAll() .requestMatchers("/").authenticated() .anyRequest().authenticated() ) .headers().frameOptions().sameOrigin() .and() .csrf().disable() // 开启 formlogin ,也就是登录页面 .formLogin() .usernameParameter("un") .passwordParameter("pw") // .successForwardUrl("/") // .failureForwardUrl("/login") .and() // 这个 Filter 可以验证 BearerToken,解析认证 .addFilterAfter(new BearerTokenAuthenticationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class) ; return http.build(); } // @formatter:on // 密码加密方式,配置该方式后,切记数据库用户密码也要使用加密的 @Bean PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } AuthenticationManager authenticationManager() { return new ProviderManager(Arrays.asList(new JwtAuthenticationProvider(jwtDecoder))); } } Spring Authorization Server 认证配置 Spring Authorization Server 框架里面已经配置了关于Oauth2与OIDC的过滤器与认证器。源码暂时不介绍,后续有机会介绍。 版本: org.springframework.security:spring-security-oauth2-authorization-server:1.0.1 @Configuration public class AuthorizationServerConfiguration2 { /** * 配置 oauth2 相关接口的拦截执行链, 具体的接口配置在 AuthorizationServerSettings 中。 * @param http * @return * @throws Exception */ @Bean @Order(1) public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception { // 这里配置了当前 FilterChain 只会拦截oauth2相关的请求 OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http); http.getConfigurer(OAuth2AuthorizationServerConfigurer.class) .authorizationEndpoint(oAuth2AuthorizationEndpointConfigurer -> { oAuth2AuthorizationEndpointConfigurer.authenticationProviders(authenticationProviders -> { // 配置授权码生成策略 for (AuthenticationProvider authenticationProvider : authenticationProviders) { log.info(" consumer authenticationProvider , current -> {} ", authenticationProvider.getClass().getName()); if(authenticationProvider instanceof OAuth2AuthorizationCodeRequestAuthenticationProvider oAuth2AuthorizationCodeRequestAuthenticationProvider) { oAuth2AuthorizationCodeRequestAuthenticationProvider.setAuthorizationCodeGenerator(authorizationCodeGenerator()); } else if(authenticationProvider instanceof OAuth2AuthorizationConsentAuthenticationProvider oAuth2AuthorizationConsentAuthenticationProvider) { oAuth2AuthorizationConsentAuthenticationProvider.setAuthorizationCodeGenerator(authorizationCodeGenerator()); } } }); }) .authorizationService(new InMemoryOAuth2AuthorizationService()) // 认证后token存储配置,默认在内存,可配置Redis与DB .oidc(Customizer.withDefaults()); // Enable OpenID Connect 1.0 http // Redirect to the login page when not authenticated from the // authorization endpoint .exceptionHandling((exceptions) -> exceptions .authenticationEntryPoint( new LoginUrlAuthenticationEntryPoint("/login")) ) // 使用 access_token 的方式 .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt) ; return http.build(); } // 这里是配置一个内存 Client // @Bean // public RegisteredClientRepository registeredClientRepository() { // RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString()) // .clientId("messaging-client") // .clientSecret(new BCryptPasswordEncoder().encode("secret")) // .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC) // .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) // .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN) // .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) // .redirectUri("http://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc") // .redirectUri("http://127.0.0.1:8080/authorized") // .scope(OidcScopes.OPENID) // .scope(OidcScopes.PROFILE) // .scope("message.read") // .scope("message.write") // .clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build()) // .build(); // // return new InMemoryRegisteredClientRepository(registeredClient); // } // 配置数据库查询的 Client @Bean public RegisteredClientRepository registeredClientRepository(@Qualifier("customJdbcTemplate") JdbcTemplate jdbcTemplate) { return new JdbcRegisteredClientRepository(jdbcTemplate); } // 配置JWT的生成方式 @Bean public JWKSource jwkSource() { KeyPair keyPair = generateRsaKey(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); RSAKey rsaKey = new RSAKey.Builder(publicKey) .privateKey(privateKey) .keyID(UUID.randomUUID().toString()) .build(); JWKSet jwkSet = new JWKSet(rsaKey); return new ImmutableJWKSet(jwkSet); } private static KeyPair generateRsaKey() { KeyPair keyPair; try { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(2048); keyPair = keyPairGenerator.generateKeyPair(); } catch (Exception ex) { throw new IllegalStateException(ex); } return keyPair; } // 配置JWT的生成方式 @Bean public JwtDecoder jwtDecoder(JWKSource jwkSource) { return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource); } @Bean public AuthorizationServerSettings authorizationServerSettings() { return AuthorizationServerSettings.builder().build(); } /** * 配置自定义的授权码 authorization_code,默认实现:OAuth2AuthorizationCodeGenerator * - 下面简单配置成为了 UUID 的形式。 */ public OAuth2TokenGenerator authorizationCodeGenerator() { return context -> { log.info(" use custom authorization_code creator "); if (context.getTokenType() == null || !OAuth2ParameterNames.CODE.equals(context.getTokenType().getValue())) { return null; } String authorizationCode = UUID.randomUUID().toString().replaceAll("-", ""); Instant issuedAt = Instant.now(); Instant expiresAt = issuedAt.plus(context.getRegisteredClient().getTokenSettings().getAuthorizationCodeTimeToLive()); return new OAuth2AuthorizationCode(authorizationCode, issuedAt, expiresAt); }; } } Resource Server 授权配置 授权服务器配置。 @Configuration @EnableMethodSecurity(securedEnabled = true) public class ResourceConfig { @Bean @Order(-100) SecurityFilterChain resourceSecurityFilterChain(HttpSecurity http) throws Exception { // 配置授权服务器认证方式 http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt); // 配置授权职责链端点 RequestMatcher requestMatcher = new AntPathRequestMatcher("/resource/**"); http.securityMatcher(requestMatcher); http.authorizeHttpRequests(matcherRegistry -> { matcherRegistry.anyRequest().authenticated(); }); return http.build(); } }

配置如上,完成一个简单的基于授权码的认证授权服务器,后面还会找个时间写一个Spring Security源码解析的文章。 后续有问题可以在公众号中咨询,看到会回复。

备注

Pasted image 20230504113822.png

示例一个认证整体流程的Filter,如果需要自定义扩展,可以实现下面几个类 OAuth2AuthorizationEndpointFilter

OAuth2AuthorizationEndpointFilter:OAuth 2.0授权代码授予的过滤器,它处理OAuth 2.0授权请求和同意的处理。

默认接口:/oauth2/authorize

AuthenticationConverter:解析请求request中的client信息,将其封装成Authentication对象,用于后期处理。

OAuth2AuthorizationCodeAuthenticationConverter:授权码处理converter OAuth2AuthorizationConsentAuthenticationConverter:处理同意的请求

AuthenticationManager:处理身份认证请求。默认处理器是:ProviderManager

AuthenticationProvider: 处理特定身份认证的实现。 OAuth2AuthorizationCodeAuthenticationProvider:授权码认证的provider OAuth2AuthorizationCodeAuthenticationProvider.OAuth2AuthorizationService 配置这个参数用来解析token


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3